--[[
任务模块辅助功能函数
--]]

local Msg = require("core.Msg")
local ExcelMonsterConf = require("excel.Monster")
local ExcelCollectConf = require("excel.Collect")
local ExcelTaskConf = require("excel.Task")
local ExcelNpcConf = require("excel.Npc")
local TaskDefine = require("task.Define")
local TaskAction = require("task.TaskAction")
local TaskLogic = require("task.TaskLogic")
local Guide = require("task.Guide")
local Duanceng = require("task.Duanceng")
local Grid = require("bag.Grid")
local ItemDefine = require("bag.ItemDefine")
local RoleUIControl  = require("role.RoleUIControl")
local ExcelLevelRewardConf = require("excel.LevelReward")
local TaskGroup = require("task.TaskGroup")
local BountyLogic = require("task.BountyLogic")
local CopyConfig = require("excel.Map").copy
local OperateActFL = require("activity.OperateActFL")
local OperateActDefine = require("activity.Define")

local RetCanDoTasks = {} 
local RetDoingTasks = {}
local RetRewardItem = {}
local RewardItemGridCache = {}		-- 任务奖励道具grid缓存 避免频繁new grid
local ChapterRewardItemGridCache = {}  --章回奖励缓存
local DescCache = {}				-- 任务描述缓存 因为任务描述里面有些特殊字符是要替换的 为了避免频繁每次都字符串查找替换浪费cpu
local DescFlyCache = {}				-- 任务描述中目标坐标的缓存 

function getTaskConfig(taskID)
	if ExcelTaskConf.Task[taskID] then return ExcelTaskConf.Task[taskID] end
	if ExcelTaskConf.Bounty[taskID] then return ExcelTaskConf.Bounty[taskID] end
	if ExcelTaskConf.FamilyBountyTask[taskID] then return ExcelTaskConf.FamilyBountyTask[taskID] end
	return nil
end

-- 获得角色的可接任务列表
function getCanDo(human)
	local hasMain = nil
	local len = 0
	for taskID, config in pairs(ExcelTaskConf.Task) do
		if config.mainType ~= TaskDefine.TASK_TYPE_1_DAILY and TaskLogic.taskCanAccept(human, taskID) == TaskDefine.TASK_ACCEPT_OK then
				len = len + 1
				RetCanDoTasks[len] = taskID
				if config.mainType == TaskDefine.TASK_TYPE_1_MAIN then
					hasMain = true
				end
		end
	end
	
	if hasMain == nil and RoleUIControl.getMaxDoingMainTaskID(human) == 0 then
		-- 找下一个暂时还不可接的主线任务
		local nMinId = 0
		local taskFinishID = RoleUIControl.getMaxFinishMainTaskID(human) 
		local taskFinishConfig = ExcelTaskConf.Task[taskFinishID]
		if taskFinishConfig and taskFinishConfig.nextTaskId > 0 then 
			nMinId = taskFinishConfig.nextTaskId 
		end		
		if nMinId > 0 then
			len = len + 1
			RetCanDoTasks[len] = nMinId
			Duanceng.sendDuancengInfo(human);
		end
	end
	
	return len, RetCanDoTasks
end

-- 获得角色的已接任务列表
function getDoing(human)
	local len = 0
	for  i = 0, human.db.taskRecordLen -1 do
	   local record = human.db.taskRecord[i]
		 if record.status == TaskDefine.TASK_ACCEPTED then
			len = len + 1
			RetDoingTasks[len] = record.taskid
		 end
	end
	return len, RetDoingTasks
end

local guildIdStr = {}
local taskGuildStr = {}
local listGuildStr = {}
for i = 1, 5 do
	guildIdStr[i] = "guildId" .. i
	taskGuildStr[i] = "taskGuild" .. i
	listGuildStr[i] = "listGuild" .. i
end

-- 设置任务节点信息
function setTaskNode(taskNode, taskID, human)
	local taskConfig = getTaskConfig(taskID) -- 任务配置信息
	local groupID = taskConfig.groupId or 0
	local groupConfig = ExcelTaskConf.TaskGroup[groupID] -- 任务组配置信息
	local taskRecordInfo = TaskLogic.getTaskRecord(human,taskID)
	
	-- 任务基础信息
	taskNode.taskID = taskID
	taskNode.taskName = taskConfig.name
	taskNode.taskPrefix = taskConfig.prefix
	taskNode.taskGroupID = groupID
	if groupConfig ~= nil then 
		taskNode.taskGroupName = groupConfig.name
	else
		taskNode.taskGroupName = ""
	end
	
	taskNode.taskDesc1 = replaceDesc(taskConfig.desc1 or "", taskConfig, taskID, 1)
	taskNode.taskDesc2 = replaceDesc(taskConfig.desc2, taskConfig, taskID, 2)
	taskNode.taskDesc3 = replaceDesc(taskConfig.desc3, taskConfig, taskID, 3)
	
	taskNode.taskLevel = taskConfig.level or 0
	taskNode.taskType1 = taskConfig.mainType
	taskNode.taskType2 = TaskAction.getTaskType2(taskConfig)
	
	-- 任务次数
  if taskNode.taskType1 == TaskDefine.TASK_TYPE_1_DAILY then
     taskNode.taskCurTimes = human.db.taskGroupCnt
     taskNode.taskMaxTimes = TaskGroup.taskMaxGroupCnt(human)
  elseif taskNode.taskType1 == TaskDefine.TASK_TYPE_1_BOUNTY then
     taskNode.taskCurTimes = human.db.bountyDoCnt
     taskNode.taskMaxTimes = BountyLogic.getMaxCnt(human)
  else
	   taskNode.taskCurTimes = 1
	   taskNode.taskMaxTimes = 1
	end	
	-- 任务对象
	if taskRecordInfo and taskRecordInfo.finishFlag ~= TaskDefine.TASK_FINISH_FLAG_NONE then
		taskNode.taskCanFinish = 1
	else
		taskNode.taskCanFinish = 0
	end
	TaskAction.setTaskObj(taskNode, human, taskID, taskConfig, taskRecordInfo)
	
	-- 任务npc
	if not taskConfig.startNpcId or taskConfig.startNpcId == 0 then
		taskNode.beginNPC[0] = 0
		taskNode.beginTalk = ""
	else
		taskNode.beginNPC[0] = 1
		taskNode.beginNPC[1].id = taskConfig.startNpcId
		taskNode.beginNPC[1].flag = ExcelNpcConf.npc[taskConfig.startNpcId].exist_map
		taskNode.beginNPC[1].mapID = ExcelNpcConf.npc[taskConfig.startNpcId].mapID
		taskNode.beginNPC[1].mapX = ExcelNpcConf.npc[taskConfig.startNpcId].mapX
		taskNode.beginNPC[1].mapY = ExcelNpcConf.npc[taskConfig.startNpcId].mapY
		taskNode.beginTalk = taskConfig.startTalk
	end
	if taskConfig.endNpcId == 0 then
		taskNode.endNPC[0] = 0
		taskNode.endTalk = ""
	else
		taskNode.endNPC[0] = 1
		taskNode.endNPC[1].id = taskConfig.endNpcId
		if not ExcelNpcConf.npc[taskConfig.endNpcId] then
			assert(nil, taskConfig.endNpcId)
		end
		taskNode.endNPC[1].flag = ExcelNpcConf.npc[taskConfig.endNpcId].exist_map
		taskNode.endNPC[1].mapID = ExcelNpcConf.npc[taskConfig.endNpcId].mapID
		taskNode.endNPC[1].mapX = ExcelNpcConf.npc[taskConfig.endNpcId].mapX
		taskNode.endNPC[1].mapY = ExcelNpcConf.npc[taskConfig.endNpcId].mapY
		taskNode.endTalk = taskConfig.endTalk
	end
	
	-- 任务奖励
	local exp, worldExpAdd = getRewardExp(taskConfig, human)
	taskNode.rewardExp = exp + worldExpAdd
	taskNode.rewardMoney = getRewardMoney(taskConfig, human)
	taskNode.rewardZhangong = getRewardZhangong(taskConfig, human)
	taskNode.rewardWushuang = getRewardWushuang(taskConfig, human)
	taskNode.rewardWeiwang  = getRewardWeiwang(taskConfig, human)
	taskNode.rewardRongyu   = getRewardRongyu(taskConfig, human)
	taskNode.rewardFamilyContribution = getRewardFamilyContribution(taskConfig, human)
	taskNode.rewardFamilyMoney = getRewardFamilyExp(taskConfig, human)
	
	local itemCount, itemGrids = getRewardItem(taskID, taskConfig, human)
	taskNode.rewardItems[0] = itemCount
	for i = 1, itemCount do 
		Grid.makeItem(itemGrids[i], taskNode.rewardItems[i], 0, human)
	end 
	
	local itemCountF, itemGridsF = getRewardItemFinal(taskID, taskConfig, human)
	taskNode.rewardItemsFinal[0] = itemCountF
	for i = 1, itemCountF do 
		Grid.makeItem(itemGridsF[i], taskNode.rewardItemsFinal[i], 0, human)
	end 	
	
	-- 自动完成
	taskNode.autoComplete = taskConfig.autoComplete or 0
	
	-- 任务颜色
	taskNode.taskColor = taskConfig.color or 1
	
	-- 是否支持快速传送
	taskNode.taskCanFly = taskConfig.canFly or 0
	
	-- 任务是否有movie要播放
	taskNode.movie1 = (taskConfig.movie1 and taskConfig.movie1[1]) and 1 or 0
	taskNode.movie2 = (taskConfig.movie2 and taskConfig.movie2[1]) and 1 or 0
	taskNode.movie3 = (taskConfig.movie3 and taskConfig.movie3[1]) and 1 or 0
	
	--章回
	local chapter = taskConfig.chapter and #taskConfig.chapter>1 and ExcelTaskConf.Chapter[taskConfig.chapter[1]]
	taskNode.taskChapterIcon = chapter and chapter.icon or 0
	taskNode.taskChapterCur  = chapter and taskConfig.chapter[2] or 0
	taskNode.taskChapterTotal = chapter and chapter.total or 0
	local chapterReward = getChapterReward(taskConfig, true)
	if not chapterReward then
	   taskNode.chapterReward[0] = 0
	else
	   taskNode.chapterReward[0] = 1
	   Grid.makeItem(chapterReward, taskNode.chapterReward[1], 0, human )   
	end
	
	taskNode.totalDesc = taskConfig.descTotal or ""
	-- 任务引导
	for i=1,5 do
		local guideID = taskConfig[guildIdStr[i]] or 0
		taskNode[taskGuildStr[i]] = guideID
		
		local guideList = taskNode[listGuildStr[i]]
		if guideID~=0 then
			Guide.setGuideList(guideID,guideList)
		else
			guideList[0] = 0
		end
	end
end

function getFBountyRewardConf(rewardLink, lv)
	if not rewardLink or not lv then
		return
	end
	
	for i = 1, #rewardLink do
		local conf = ExcelTaskConf.FamilyBountyReward[rewardLink[i]]
		if lv >= conf.lv_min and lv <= conf.lv_max then
			return conf
		end
	end
end

function getRewardExp(taskConfig, human)
	if not taskConfig.reward then
		local rconf = getFBountyRewardConf(taskConfig.rewardLink, human.db.lv)
		if rconf then
			return rconf.exp, 0
		end
		return 0, 0
	end
	local retExp = taskConfig.reward.exp or 0
	local retWorldExpAdd = 0
	if taskConfig.reward.expLv then
		retExp = retExp + ExcelLevelRewardConf[taskConfig.reward.expLv][human.db.lv].exp
--	retWorldExpAdd = retWorldExpAdd -- + math.ceil(ExcelLevelRewardConf[taskConfig.reward.expLv][human.db.lv].exp * WorldExpAdd.getWorldExpAdd(human) / 100)
	end
	if taskConfig.reward.dexp then
		retExp = retExp + taskConfig.reward.dexp
--		retWorldExpAdd = retWorldExpAdd -- + math.ceil(taskConfig.reward.dexp * WorldExpAdd.getWorldExpAdd(human) / 100)
	end
  if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
     retExp = retExp * 2
--   retWorldExpAdd = retWorldExpAdd*2
  end
	return retExp, retWorldExpAdd
end

function getRewardMoney(taskConfig, human)
	if not taskConfig.reward then
		return 0
	end
	local retMoney = taskConfig.reward.yinliang or 0
	if taskConfig.reward.yinliangLv then
		retMoney = retMoney + ExcelLevelRewardConf[taskConfig.reward.yinliangLv][human.db.lv].yinliang
	end
	
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
	   retMoney = retMoney * 2
	end
	return retMoney
end

function getRewardZhangong(taskConfig, human)
	if not taskConfig.reward then
		return 0
	end
	local ret = taskConfig.reward.zhangong or 0
	if taskConfig.reward.zhangongLv then
	   ret = ret + ExcelLevelRewardConf[taskConfig.reward.zhangongLv][human.db.lv].zhangong
	end
	if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
     ret = ret * 2
  end
	return ret
end

function getRewardWeiwang(taskConfig, human)
  if not taskConfig.reward then
      return 0
  end
  local ret = taskConfig.reward.weiwang or 0 
  if taskConfig.reward.weiwangLv then
      ret = ret + ExcelLevelRewardConf[taskConfig.reward.weiwangLv][human.db.lv].weiwang
  end
  if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
     ret = ret * 2
  end
  return ret
end

function getRewardRongyu(taskConfig, human)
  if not taskConfig.reward then
      return 0
  end
  local ret = taskConfig.reward.rongyu or 0
  if taskConfig.reward.rongyuLv then
      ret = ret + (ExcelLevelRewardConf[taskConfig.reward.rongyuLv][human.db.lv].rongyu or 0)
  end
  if taskConfig.level_min and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
     ret = ret * 2
  end
  return ret
end

function getRewardWushuang(taskConfig, human)
  if not taskConfig.reward then
      return 0
  end
  local ret = taskConfig.reward.wushuang or 0 
  if taskConfig.reward.wushuangLv then
      ret = ret + ExcelLevelRewardConf[taskConfig.reward.wushuang][human.db.lv].wushuang
  end
  if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
     ret = ret * 2
  end
  return ret
end

function getRewardItem(taskID, taskConfig, human)
	if not taskConfig.reward then
		return 0
	end
	local count = 0
	if taskConfig.reward.item then
		for itemID, itemInfo in pairs(taskConfig.reward.item) do
			if RewardItemGridCache[taskID] == nil then
				RewardItemGridCache[taskID] = {}
			end
			if RewardItemGridCache[taskID][itemID] == nil then
				if not itemInfo[2] then
					RewardItemGridCache[taskID][itemID] = {}
					Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[1], true)
				else
					RewardItemGridCache[taskID][itemID] ={}
					Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[1], true, ItemDefine.getQualityOut(itemInfo[2]))
				end
			end
			
			if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY then
			  if OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
			   if RewardItemGridCache[taskID][itemID].cnt == itemInfo[1] then
			       RewardItemGridCache[taskID][itemID].cnt = RewardItemGridCache[taskID][itemID].cnt*2
			   end
			  else
			       RewardItemGridCache[taskID][itemID].cnt = itemInfo[1]
			  end
			end
			count = count + 1
			RetRewardItem[count] = RewardItemGridCache[taskID][itemID]
		end
	end	
	if taskConfig.reward.sbitem then
	  if human.db.shenbingLen > 0 and taskConfig.reward.sbitem[human.db.shenbing[0].id] then
	     local conf = taskConfig.reward.sbitem[human.db.shenbing[0].id] 
	     for _, itemInfo in pairs(conf) do
	        local itemID = itemInfo[1]
	        if RewardItemGridCache[taskID] == nil then
            RewardItemGridCache[taskID] = {}
          end
          if RewardItemGridCache[taskID][itemID] == nil then
            if not itemInfo[3] then
              RewardItemGridCache[taskID][itemID] = {}
              Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[2], true)
            else
              RewardItemGridCache[taskID][itemID] ={}
              Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[2], true, ItemDefine.getQualityOut(itemInfo[3]))
            end
          end
          
          if taskConfig.mainType == TaskDefine.TASK_TYPE_1_BOUNTY and OperateActFL.onCheckActIsRunning(OperateActDefine.OPERATEACT_TYPE_BOUNTYDOUBLE) then --双倍运营活动
            if RewardItemGridCache[taskID][itemID].cnt == itemInfo[1] then
              RewardItemGridCache[taskID][itemID].cnt = RewardItemGridCache[taskID][itemID].cnt*2
            end
          end
          count = count + 1
          RetRewardItem[count] = RewardItemGridCache[taskID][itemID]
	     end
	  end
	end
	return count, RetRewardItem
end

function getRewardItemFinal(taskID, taskConfig)--, human)
	local count = 0
	if not taskConfig.reward then
		return count
	end
	
	if taskConfig.reward.fitem then
		for itemID, itemInfo in pairs(taskConfig.reward.fitem) do
			if RewardItemGridCache[taskID] == nil then
				RewardItemGridCache[taskID] = {}
			end
			if RewardItemGridCache[taskID][itemID] == nil then
				if not itemInfo[2] then
					RewardItemGridCache[taskID][itemID] = {}
					Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[1], true)
				else
					RewardItemGridCache[taskID][itemID] = {}
					Grid.create(RewardItemGridCache[taskID][itemID],itemID, itemInfo[1], true, ItemDefine.getQualityOut(itemInfo[2]))
				end
			end
			count = count + 1
			RetRewardItem[count] = RewardItemGridCache[taskID][itemID]
		end
	end
	return count, RetRewardItem
end

function getChapterReward(taskConfig, show)

  if not taskConfig.chapter or #taskConfig.chapter <2 then
      return 
  end
  
  local chapter = ExcelTaskConf.Chapter[taskConfig.chapter[1]]
  if not chapter or #chapter.reward < 2  then
      return 
  end
  if ChapterRewardItemGridCache[taskConfig.chapter[1]] == nil then
      ChapterRewardItemGridCache[taskConfig.chapter[1]] = {}
      if not chapter.reward[3] then
            Grid.create(ChapterRewardItemGridCache[taskConfig.chapter[1]],chapter.reward[1], chapter.reward[2], true)      
      else
            Grid.create(ChapterRewardItemGridCache[taskConfig.chapter[1]],chapter.reward[1], chapter.reward[2], true, ItemDefine.getQualityOut(chapter.reward[3]))  
      end    
  end
  if show then
      return ChapterRewardItemGridCache[taskConfig.chapter[1]]
  end
  if taskConfig.chapter[2] == chapter.total-1 then  
      return ChapterRewardItemGridCache[taskConfig.chapter[1]]
  end
end


function getRewardFamilyContribution(taskConfig, human)
	if not taskConfig.reward then
		local rconf = getFBountyRewardConf(taskConfig.rewardLink, human.db.lv)
		if rconf then
			return rconf.family_contribution
		end
	end
	return 0	
end

function getRewardFamilyExp(taskConfig, human)
	if not taskConfig.reward then
		local rconf = getFBountyRewardConf(taskConfig.rewardLink, human.db.lv)
		if rconf then
			return rconf.family_exp
		end
	end
	return 0
end

function refreshDoing(human)
	local msgRet = Msg.gc.GC_TASK_ADD
	
	msgRet.canDoTasks[0] = 0
	-- 获得角色的已接任务列表
	local doingTasksLen, doingTasks = getDoing(human)
	
	msgRet.doingTasks[0] = doingTasksLen
	for i = 1, doingTasksLen do
		if msgRet.doingTasks[0] > 16 then 
			msgRet.doingTasks[0] = 16
			break 
		end
		local taskID = doingTasks[i]
		local taskNode = msgRet.doingTasks[i]
		setTaskNode(taskNode, taskID, human)
	end
	
	if msgRet.doingTasks[0] > 0 then
		Msg.send(msgRet, human.fd)
	end
end

function refreshCanDoTask(human, taskID)
  local msgRet = Msg.gc.GC_TASK_ADD  
  msgRet.canDoTasks[0] = 1  
  msgRet.doingTasks[0] = 0
  setTaskNode(msgRet.canDoTasks[1], taskID, human)
  Msg.send(msgRet, human.fd)
end


--[[
<beginnpc> 代表接任务npc信息
<endnpc> 代表交任务npc信息
<monster:id> 代表打怪对象id信息
<collect:id> 代表采集对象id信息
<item:id>	代表收集对象id信息
<targetcnt:id> 目标数量 -- 这个起始服务器端不处理 直接交给客户端处理
<place:101:50:100:> 特定地点
<target:101:50:100:10001:1:> 特定目标
<npc:101> 特定npc信息
<sa:1:>特定操作 1采矿 2钓鱼
<open:1:>打开面板 具体定义见PanelDefine.lua
<buy:itemid>打开快速购买界面
寻路信息里面 1 npc 2 采集物 3 怪物
--]]
function replaceDesc(desc, taskConfig, taskID, descIndex)
	if desc == nil or #desc == 0 then return "" end

	if DescCache[taskID] == nil then DescCache[taskID] = {} end
	if DescFlyCache[taskID] == nil then DescFlyCache[taskID] = {} end	
	if DescCache[taskID][descIndex] ~= nil then return DescCache[taskID][descIndex] end
	if DescFlyCache[taskID][descIndex] == nil then  DescFlyCache[taskID][descIndex] = {} end

	local temp = desc
	
	local i, j
	while (true) do
		i, j = string.find(temp, "<endnpc>")
		if not i then break end
		
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, j + 1)
--		print("taskConfig.endNpcId",taskConfig.endNpcId)
--		print("ExcelNpcConf.npc[taskConfig.endNpcId],taskID",ExcelNpcConf.npc[taskConfig.endNpcId],taskID)		
		temp = tempLeft .. "<a href='event:" .. ExcelNpcConf.npc[taskConfig.endNpcId].mapID .. "," .. ExcelNpcConf.npc[taskConfig.endNpcId].mapX .. "," .. ExcelNpcConf.npc[taskConfig.endNpcId].mapY .. "," .. taskConfig.endNpcId .. ",1".. "'><u>"  .. "<font color='#00ff00'>" .. ExcelNpcConf.npc[taskConfig.endNpcId].name .. "</font>" .. "</u></a>" .. tempRight 
		DescFlyCache[taskID][descIndex][1] = {mapID=ExcelNpcConf.npc[taskConfig.endNpcId].mapID, mapX=ExcelNpcConf.npc[taskConfig.endNpcId].mapX, mapY=ExcelNpcConf.npc[taskConfig.endNpcId].mapY}
	end

	i, j = string.find(temp, "<beginnpc>")
	if i then
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, j + 1)		
		temp = tempLeft .. "<a href='event:" .. ExcelNpcConf.npc[taskConfig.startNpcId].mapID .. "," .. ExcelNpcConf.npc[taskConfig.startNpcId].mapX .. "," .. ExcelNpcConf.npc[taskConfig.startNpcId].mapY .. "," .. taskConfig.startNpcId .. ",1".. "'><u>"  .. "<font color='#00ff00'>" .. ExcelNpcConf.npc[taskConfig.startNpcId].name .. "</font>" .. "</u></a>" .. tempRight 
		DescFlyCache[taskID][descIndex][1] = { mapID=ExcelNpcConf.npc[taskConfig.startNpcId].mapID, mapX=ExcelNpcConf.npc[taskConfig.startNpcId].mapX, mapY=ExcelNpcConf.npc[taskConfig.startNpcId].mapY}
	end
	
	temp = handleMonster(temp, DescFlyCache[taskID][descIndex])
		
	temp = handleCollect(temp, DescFlyCache[taskID][descIndex])
	
	temp = handleItem(temp)
	
	temp = handleNpc(temp, DescFlyCache[taskID][descIndex])
	
	temp = handlePlace(temp, DescFlyCache[taskID][descIndex])
	
	temp = handleTarget(temp, DescFlyCache[taskID][descIndex])
	
	temp = handleSA(temp, DescFlyCache[taskID][descIndex])
	
	temp = handleOpen(temp)
	
	temp = handleCopy(temp, DescFlyCache[taskID][descIndex])
	
	temp = handleAct(temp, DescFlyCache[taskID][descIndex])
	
	DescCache[taskID][descIndex] = temp
	return temp
end

function handleMonster(temp, tb)
	while (true) do
		i, j = string.find(temp, "<monster:")
		if not i then break end
		m, n = string.find(temp, ">", j + 1)
		if not m then break end
		
		local id = string.sub(temp, j + 1, m-1) + 0
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, n + 1)
		temp = tempLeft .. "<a href='event:" .. ExcelMonsterConf.monster[id].mapID .. "," .. ExcelMonsterConf.monster[id].mapX .. "," .. ExcelMonsterConf.monster[id].mapY.. "," .. id .. ",3" .. "'><u>"  .. "<font color='#00ff00'>" ..ExcelMonsterConf.monster[id].name .. "</font>" .. "</u></a>" .. tempRight 	
		if tb then
			tb[#tb + 1] = {mapID=ExcelMonsterConf.monster[id].mapID, mapX=ExcelMonsterConf.monster[id].mapX, mapY=ExcelMonsterConf.monster[id].mapY}
		end
	end
	return temp
end

function handleCollect(temp, tb)
	while (true) do
		i, j = string.find(temp, "<collect:")
		if not i then break end
		m, n = string.find(temp, ">", j + 1)
		if not m then break end
		
		local id = string.sub(temp, j + 1, m-1) + 0
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, n + 1)
		temp = tempLeft .. "<a href='event:" .. ExcelCollectConf.Collect[id].mapID .. "," .. ExcelCollectConf.Collect[id].mapX .. "," .. ExcelCollectConf.Collect[id].mapY.. ",".. id .. ",2" .. "'><u>"  .. "<font color='#00ff00'>" ..ExcelCollectConf.Collect[id].name .. "</font>" .. "</u></a>" .. tempRight 	
		if tb then
			tb[#tb + 1] = {mapID=ExcelCollectConf.Collect[id].mapID, mapX=ExcelCollectConf.Collect[id].mapX, mapY=ExcelCollectConf.Collect[id].mapY}
		end
	end
	return temp
end

function handleItem(temp)
	while (true) do
		i, j = string.find(temp, "<item:")
		if not i then break end
		m, n = string.find(temp, ">", j + 1)
		if not m then break end
		
		local id = string.sub(temp, j + 1, m-1) + 0
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, n + 1)
		temp = tempLeft .. "<a href='event:item,"..id..","..ItemDefine.getValue(id,"name").."'><font color='#00ff00'><u>" .. ItemDefine.getValue(id,"name") .. "</u></font></a>" .. tempRight 	
	end
	return temp
end

function handleNpc(temp, tb)
	while (true) do
		i, j = string.find(temp, "<npc:")
		if not i then break end
		m, n = string.find(temp, ">", j + 1)
		if not m then break end
		
		local id = string.sub(temp, j + 1, m-1) + 0
		local tempLeft = string.sub(temp, 1, i - 1)
		local tempRight = string.sub(temp, n + 1)
		temp = tempLeft .. "<a href='event:" .. ExcelNpcConf.npc[id].mapID .. "," .. ExcelNpcConf.npc[id].mapX .. "," .. ExcelNpcConf.npc[id].mapY .. "," .. id .. ",1" .. "'><u>" .. "<font color='#00ff00'>" .. ExcelNpcConf.npc[id].name .. "</font>" .. "</u></a>" .. tempRight 
		if tb then
			tb[#tb + 1] = {mapID=ExcelNpcConf.npc[id].mapID, mapX=ExcelNpcConf.npc[id].mapX, mapY=ExcelNpcConf.npc[id].mapY}
		end
	end
	return temp
end

function handlePlace(temp, tb)
	while (true) do
		i, j = string.find(temp, "<place:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end
				
		local mapid = string.sub(temp, j + 1, m - 1) + 0
		local m2, n2 = string.find(temp, ":", n + 1)
		if not m2 then break end
		
		local x = string.sub(temp, n + 1, m2 - 1) + 0
		local m3, n3 = string.find(temp, ":", n2 + 1) 
		if not m3 then break end
		local y = string.sub(temp, n2 + 1, m3 - 1) + 0
		local m4, n4 = string.find(temp, ">", n3 + 1)
		if not m4 then break end
			
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n4 + 1)
		local tempMid = string.sub(temp, n3 + 1, m4 - 1)
		temp = tempLeft .. "<a href='event:" .. mapid .. "," .. x .. "," .. y.. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 	
		if tb then
			tb[#tb + 1] = {mapID=mapid, mapX=x, mapY=y}
		end
	end
	return temp
end

function handleTarget(temp, tb)
	while (true) do
		i, j = string.find(temp, "<target:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end
				
		local mapid = string.sub(temp, j + 1, m - 1) + 0
		local m2, n2 = string.find(temp, ":", n + 1)
		if not m2 then break end
		
		local x = string.sub(temp, n + 1, m2 - 1) + 0
		local m3, n3 = string.find(temp, ":", n2 + 1) 
		if not m3 then break end
		local y = string.sub(temp, n2 + 1, m3 - 1) + 0

		local m4, n4 = string.find(temp, ":", n3 + 1) 
		if not m4 then break end
		local id = string.sub(temp, n3 + 1, m4 - 1) + 0

		local m5, n5 = string.find(temp, ":", n4 + 1) 
		if not m5 then break end
		local idtype = string.sub(temp, n4 + 1, m5 - 1) + 0

		local m6, n6 = string.find(temp, ">", n5 + 1)
		if not m6 then break end
			
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n6 + 1)
		local tempMid = string.sub(temp, n5 + 1, m6 - 1)
		temp = tempLeft .. "<a href='event:" .. mapid .. "," .. x .. "," .. y.. "," .. id .. "," .. idtype .. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 
		if tb then
			tb[#tb + 1] = {mapID=mapid, mapX=x, mapY=y}
		end
	end
	return temp
end

-- 注意 在task描述里面server端没有处理这个 因为客户端需要cur和max 所以这块丢给客户端处理了
function handleTargetCnt(temp, cur, max)
	while (true) do
		i, j = string.find(temp, "<targetcnt:")
		if not i then break end
		
		local m5, n5 = string.find(temp, ">", j + 1)
		if not m5 then break end
		
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n5 + 1)
		
		temp = tempLeft .. "(" .. cur .. "/" .. max .. ")" .. tempRight 	
	end
	return temp
end

function handleSA(temp, tb)
	while (true) do
		i, j = string.find(temp, "<sa:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end

		local id = string.sub(temp, j + 1, m - 1) + 0
		
		local m5, n5 = string.find(temp, ">", n + 1)
		if not m5 then break end
		
		local mapid, mapX, mapY, m4, n4
		local m2, n2 = string.find(temp, ":", n + 1)
		if m2 and m2 < m5 then 
			mapid = string.sub(temp, n + 1, m2 - 1) + 0
			
			local m3, n3 = string.find(temp, ":", n2 + 1)
			if not m3 then break end		
			mapX = string.sub(temp, n2 + 1, m3 - 1) + 0

			m4, n4 = string.find(temp, ":", n3 + 1)
			if not m4 then break end		
			mapY = string.sub(temp, n3 + 1, m4 - 1) + 0		
		end
		
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n5 + 1)
		if mapX and mapY then
			local tempMid = string.sub(temp, n4 + 1, m5 - 1)
			temp = tempLeft .. "<a href='event:" .. "sa" .. "," .. id .. "," .. mapid .. "," .. mapX .. "," .. mapY .. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 	
			if tb then
				tb[#tb + 1] = {mapID=mapid, mapX=mapX, mapY=mapY}
			end
		else
			local tempMid = string.sub(temp, n + 1, m5 - 1)
			temp = tempLeft .. "<a href='event:" .. "sa" .. "," .. id .. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 	
		end
	end
	return temp
end

function handleCopy(temp, tb)
	while (true) do
		i, j = string.find(temp, "<copy:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end
			
		local copyType = string.sub(temp, j + 1, m - 1) + 0
		
		local m2, n2 = string.find(temp, ":", n + 1)
		if not m2 then break end
		local copyID = string.sub(temp, n + 1, m2 - 1) + 0
	
		
		local m6, n6 = string.find(temp, ">", n2 + 1)
		if not m6 then break end

			
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n6 + 1)
		temp = tempLeft .. "<a href='event:" .. "copy,"  .. copyType .. "," .. copyID .. "'><u><font color='#00ff00'>" .. CopyConfig[copyID].name .. "</font></u></a>" .. tempRight 
		if tb then
			tb[#tb + 1] = {mapID=mapid, mapX=x, mapY=y}
		end
	end
	return temp
end

function handleAct(temp, tb)
	while (true) do
		i, j = string.find(temp, "<act:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end
			
		local copyType = string.sub(temp, j + 1, m - 1) + 0
		
		local m2, n2 = string.find(temp, ":", n + 1)
		if not m2 then break end
		local copyID = string.sub(temp, n + 1, m2 - 1) + 0
	
		
		local m6, n6 = string.find(temp, ">", n2 + 1)
		if not m6 then break end

			
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n6 + 1)
		local tempMid = string.sub(temp, n2 + 1, m6 - 1)
		
		temp = tempLeft .. "<a href='event:" .. "act,"  .. copyType .. "," .. copyID .. "'><u><font color='#00ff00'>" .. tempMid .. "</font></u></a>" .. tempRight 
		if tb then
			tb[#tb + 1] = {mapID=mapid, mapX=x, mapY=y}
		end
	end
	return temp
end

function handleOpen(temp)
	while (true) do
		i, j = string.find(temp, "<open:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end

		local id = string.sub(temp, j + 1, m - 1) + 0
		
		local m5, n5 = string.find(temp, ">", n + 1)
		if not m5 then break end
		
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n5 + 1)
		local tempMid = string.sub(temp, n + 1, m5 - 1)
		temp = tempLeft .. "<a href='event:" .. "open" .. "," .. id .. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 	
	end
	return temp
end

function handleBuy(temp)
	while (true) do
		i, j = string.find(temp, "<buy:")
		if not i then break end
		m, n = string.find(temp, ":", j + 1)
		if not m then break end

		local id = string.sub(temp, j + 1, m - 1) + 0
		
		local m5, n5 = string.find(temp, ">", n + 1)
		if not m5 then break end
		
		local tempLeft = string.sub(temp, 1, i - 1) 
		local tempRight = string.sub(temp, n5 + 1)
		local tempMid = string.sub(temp, n + 1, m5 - 1)
		temp = tempLeft .. "<a href='event:" .. "buy" .. "," .. id .. "'><u>"  .. "<font color='#00ff00'>" .. tempMid .. "</font>" .. "</u></a>" .. tempRight 	
	end
	return temp
end

function checkTaskCanFly(human, mapId, mX, mY)
	-- 获得角色的可接任务列表
	local canDoTasksLen, canDoTasks = getCanDo(human)
	for i = 1, canDoTasksLen do
		local taskID = canDoTasks[i]		
		if not DescFlyCache[taskID] or not DescFlyCache[taskID][1] then
			local taskConfig = getTaskConfig(taskID) 
			replaceDesc(taskConfig.desc1 or "", taskConfig, taskID, 1)
		end
		local mapList = DescFlyCache[taskID] and DescFlyCache[taskID][1]	
		if mapList then
			for k, v in pairs(mapList) do
				if v.mapID == mapId and mX == v.mapX and mY == v.mapY then
					return true
				end
			end
		end		
	end
	

	-- 获得角色的已接任务列表
	local doingTasksLen, doingTasks = getDoing(human)
	for i = 1, doingTasksLen do
		local taskID = doingTasks[i]
		local taskConfig = getTaskConfig(taskID) 
		local isFinish = TaskAction.isTaskActionFinish(human, taskID, taskConfig) == TaskDefine.TASK_FINISH_OK		
		local mapList 
		
		if isFinish then
			if not DescFlyCache[taskID] or not DescFlyCache[taskID][3] then				
				replaceDesc(taskConfig.desc3 or "", taskConfig, taskID, 3)
			end	
			mapList = DescFlyCache[taskID] and DescFlyCache[taskID][3]
		else 
			if not DescFlyCache[taskID] or not DescFlyCache[taskID][2] then
				replaceDesc(taskConfig.desc2 or "", taskConfig, taskID, 2)
			end				
			mapList = DescFlyCache[taskID] and DescFlyCache[taskID][2]
		end
		
		if mapList then
			for k, v in pairs(mapList) do
				if v.mapID == mapId and mX == v.mapX and mY == v.mapY then
					return true
				end
			end
		end	
	end
	
	-- 检查断层指引
	for id in pairs(ExcelTaskConf.Duanceng) do
		local mapList
		if Duanceng.DescFlyCache[id] then
			mapList = Duanceng.DescFlyCache[id]
		end
		
		if mapList then
			for k, v in pairs(mapList) do
				if v.mapID == mapId and mX == v.mapX and mY == v.mapY then
					return true
				end
			end
		end
	end
end